package guggaTests.tasks.helpers
{
	import flash.events.EventDispatcher;
	
	import flexunit.framework.TestCase;
	
	import gugga.tasks.FictiveTask;
	import gugga.tasks.helpers.IPreconditionsManager;
	import gugga.tasks.helpers.PreconditionsManagerEvent;
	import gugga.eventHelpers.EventDescriptor;
	import gugga.tasks.helpers.PreconditionsManager;
	import flash.events.Event;

	public class PreconditionsManagerTest extends TestCase
	{
		
		private var preconditionsMet : Boolean;
		private var mIsEventDispatched : Boolean = false;
	
		public function PreconditionsManagerTest()
		{
			super();
			this.preconditionsMet = false;
		}
		
		public function testConstructor() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:IPreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
			
			assertNotNull(
					"preconditionsManager should not be null after creation", 
					preconditionsManager);
			assertNotUndefined(
					"preconditionsManager should not be undefined after creation", 
					preconditionsManager);
			assertEquals(
					"preconditionsManager.isAccepting() should equals initialIsAccepting after creation", 
					preconditionsManager.isAccepting(), 
					initialIsAccepting);
		}
		
		public function testAccepting() : void
		{
			var initialIsAccepting:Boolean = false;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
				
			assertEquals(
					"preconditionsManager.isAccepting() should equals initialIsAccepting",
					preconditionsManager.isAccepting(), 
					initialIsAccepting);
			assertEquals(
					"preconditionsManager.Accepting should equals initialIsAccepting",
					preconditionsManager.Accepting, 
					initialIsAccepting);
		}
		
		public function testAddContainsRemove() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:IPreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
			
			var eventSource1:FictiveTask = new FictiveTask();
			var precondition1:EventDescriptor = new EventDescriptor(
					eventSource1, 
					"start");
			preconditionsManager.add(precondition1);
			
			assertTrue(
					"preconditionsManager should contain precondition1", 
					preconditionsManager.contains(precondition1));
			
			var eventSource2:FictiveTask = new FictiveTask();
			var precondition2:EventDescriptor = new EventDescriptor(
					eventSource2, 
					"start");
			preconditionsManager.add(precondition2);
			
			assertTrue(
					"preconditionsManager should contain precondition2", 
					preconditionsManager.contains(precondition2));
					
			assertTrue(
					"preconditionsManager should contain precondition1 and precondition2", 
					preconditionsManager.contains(precondition1) && preconditionsManager.contains(precondition2));
			
			preconditionsManager.remove(precondition1);
			assertFalse(
					"preconditionsManager should not contain precondition1 - it was removed", 
					preconditionsManager.contains(precondition1));
			
			assertTrue(
					"preconditionsManager should contain precondition2 (only precondition1 was removed)", 
					preconditionsManager.contains(precondition2));
		}
		
		public function testRemoveByEventSource() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:IPreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
			
			var eventSource1:FictiveTask = new FictiveTask();
			var precondition1:EventDescriptor = new EventDescriptor(
					eventSource1, 
					"start");
			preconditionsManager.add(precondition1);
			
			var eventSource2:FictiveTask = new FictiveTask();
			var precondition2:EventDescriptor = new EventDescriptor(
					eventSource2, 
					"start");
			preconditionsManager.add(precondition2);
			
			assertTrue(
					"preconditionsManager should contain precondition1 and precondition2", 
					preconditionsManager.contains(precondition1) && preconditionsManager.contains(precondition2));
			
			preconditionsManager.removeByEventSource(eventSource1);
			
			assertFalse(
					"preconditionsManager should not contain precondition1 - it was removed by its EventSource", 
					preconditionsManager.contains(precondition1));
			
			assertTrue(
					"preconditionsManager should contain precondition2 (only precondition1 was removed)", 
					preconditionsManager.contains(precondition2));
		}
		
		public function testReplace() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:IPreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
			
			var eventSource:FictiveTask = new FictiveTask();
			var precondition:EventDescriptor = new EventDescriptor(
					eventSource, 
					"start");
			preconditionsManager.add(precondition);
			
			assertTrue(
					"preconditionsManager should contain precondition", 
					preconditionsManager.contains(precondition));
			
			var eventSourceNew:FictiveTask = new FictiveTask();
			var preconditionNew:EventDescriptor = new EventDescriptor(
					eventSourceNew, 
					"start");
			preconditionsManager.replace(precondition, preconditionNew);
			
			assertFalse(
					"preconditionsManager should not contain precondition - it was replaced", 
					preconditionsManager.contains(precondition));
			assertTrue(
					"preconditionsManager should contain preconditionNew after replace", 
					preconditionsManager.contains(preconditionNew));
		}
		
		public function testReplaceEventSourceOnSinglePrecondition() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
			
			var eventSource:FictiveTask = new FictiveTask();
			var precondition:EventDescriptor = new EventDescriptor(
					eventSource, 
					"start");
			preconditionsManager.add(precondition);
			
			var eventSourceNew:FictiveTask = new FictiveTask();
			preconditionsManager.replaceEventSource(eventSource, eventSourceNew);
			
			eventSource.start();
			assertFalse(
					"preconditionsManager.mPreconditions checklist should not be met, because precondition's EventSource was replaced",
					preconditionsManager.PreconditionsMet);
			

			
			eventSourceNew.start();
			
			assertTrue(
					"preconditionsManager.mPreconditions checklist should be met, because the new EventSource was used to dispatch the event",
					preconditionsManager.PreconditionsMet);
		}
		
		public function testReplaceEventSourceOnMultiplePreconditions() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
			
			var eventSource1:FictiveTask = new FictiveTask();
			var precondition1:EventDescriptor = new EventDescriptor(
					eventSource1, 
					"start");
			preconditionsManager.add(precondition1);
			
			var eventSource2:FictiveTask = new FictiveTask();
			var precondition2:EventDescriptor = new EventDescriptor(
					eventSource2, 
					"start");
			preconditionsManager.add(precondition2);
			
			var eventSourceNew:FictiveTask = new FictiveTask();
			preconditionsManager.replaceEventSource(eventSource1, eventSourceNew);
			
			eventSource1.start();
			eventSource2.start();
			assertFalse(
					"preconditionsManager.mPreconditions checklist should not be met, because precondition1's EventSource was replaced",
					preconditionsManager.PreconditionsMet);
			
			eventSourceNew.start();
			assertTrue(
					"preconditionsManager.mPreconditions checklist should be met, because the new EventSource was used to dispatch the events for precondition1, and precondition2 is already met",
					preconditionsManager.PreconditionsMet);
		}
		
		public function testIgnoreAcceptAll() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
				
			var eventSource1:FictiveTask = new FictiveTask();
			var precondition1:EventDescriptor = new EventDescriptor(
					eventSource1, 
					"start");
			preconditionsManager.add(precondition1);
			
			var eventSource2:FictiveTask = new FictiveTask();
			var precondition2:EventDescriptor = new EventDescriptor(
					eventSource2, 
					"start");
			preconditionsManager.add(precondition2);
			
			preconditionsManager.ignoreAll();
			eventSource1.start();
			eventSource2.start();
			assertFalse(
					"preconditionsManager.mPreconditions checklist should not be met, because all preconditions are ignored",
					preconditionsManager.PreconditionsMet);
			
			preconditionsManager.acceptAll();
			eventSource1.start();
			eventSource2.start();
			assertTrue(
					"preconditionsManager.mPreconditions checklist should be met, because all preconditions are now accepted",
					preconditionsManager.PreconditionsMet);
		}
		
		public function testIgnoreAcceptOnSinglePrecondition() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
				
			var eventSource:FictiveTask = new FictiveTask();
			var precondition:EventDescriptor = new EventDescriptor(
					eventSource, 
					"start");
			preconditionsManager.add(precondition);
			
			preconditionsManager.ignore(precondition);
			eventSource.start();
			assertFalse(
					"preconditionsManager.mPreconditions checklist should not be met, because precondition is ignored",
					preconditionsManager.PreconditionsMet);
			
			preconditionsManager.accept(precondition);
			eventSource.start();
			assertTrue(
					"preconditionsManager.mPreconditions checklist should be met, because precondition now is accepted",
					preconditionsManager.PreconditionsMet);
		}
		
		public function testIgnoreAcceptOnMultiplePreconditions() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
				
			var eventSource1:FictiveTask = new FictiveTask();
			var precondition1:EventDescriptor = new EventDescriptor(
					eventSource1, 
					"start");
			preconditionsManager.add(precondition1);
			
			var eventSource2:FictiveTask = new FictiveTask();
			var precondition2:EventDescriptor = new EventDescriptor(
					eventSource2, 
					"start");
			preconditionsManager.add(precondition2);
			
			preconditionsManager.ignore(precondition1);
			eventSource1.start();
			eventSource2.start();
			assertFalse(
					"preconditionsManager.mPreconditions checklist should not be met, because precondition1 is ignored",
					preconditionsManager.PreconditionsMet);
			
			preconditionsManager.accept(precondition1);
			eventSource1.start();
			assertTrue(
					"preconditionsManager.mPreconditions checklist should be met, because precondition1 now is accepted and precondition2 is already met",
					preconditionsManager.PreconditionsMet);
		}
		
		public function testIgnoreAcceptEventSourceOnSinglePrecondition() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
				
			var eventSource:FictiveTask = new FictiveTask();
			var precondition:EventDescriptor = new EventDescriptor(
					eventSource, 
					"start");
			preconditionsManager.add(precondition);
			
			preconditionsManager.ignoreEventSource(eventSource);
			eventSource.start();
			assertFalse(
					"preconditionsManager.mPreconditions checklist should not be met, because precondition's EventSource is ignored",
					preconditionsManager.PreconditionsMet);
			
			preconditionsManager.acceptEventSource(eventSource);
			eventSource.start();
			assertTrue(
					"preconditionsManager.mPreconditions checklist should be met, because precondition's EventSource now is accepted",
					preconditionsManager.PreconditionsMet);
		}
		
		public function testIgnoreAcceptEventSourceOnMultiplePreconditions() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
				
			var eventSource1:FictiveTask = new FictiveTask();
			var precondition1:EventDescriptor = new EventDescriptor(
					eventSource1, 
					"start");
			preconditionsManager.add(precondition1);
			
			var eventSource2:FictiveTask = new FictiveTask();
			var precondition2:EventDescriptor = new EventDescriptor(
					eventSource2, 
					"start");
			preconditionsManager.add(precondition2);
			
			preconditionsManager.ignoreEventSource(eventSource1);
			eventSource1.start();
			eventSource2.start();
			assertFalse(
					"preconditionsManager.mPreconditions checklist should not be met, because precondition1's EventSource is ignored",
					preconditionsManager.PreconditionsMet);
			
			preconditionsManager.acceptEventSource(eventSource1);
			eventSource1.start();
			assertTrue(
					"preconditionsManager.mPreconditions checklist should be met, because precondition1's EventSource now is accepted and precondition2 is already met",
					preconditionsManager.PreconditionsMet);
		}
		
		public function testPreconditionsMetAfterCreationNoPreconditionsSpecified() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
			preconditionsManager.addEventListener(
					"preconditionsMet", 
					onPreconditionsMet);
			
			// after creation preconditionsManager.mPreconditions checklist should 
			// be empty, therefore preconditions should be met:
			assertTrue(
					"aPreconditionsManager.mPreconditions checklist should be met after creation",
					preconditionsManager.PreconditionsMet);
					
			assertEquals(
					"aPreconditionsManager.PreconditionsMet should equals aPreconditionsManager.getPreconditionsMet()", 
					preconditionsManager.PreconditionsMet, 
					preconditionsManager.getPreconditionsMet());
			
			assertFalse(
					"preconditionsManager should not raise the preconditionsMet event, when not started within a PreconditionsTask", 
					this.preconditionsMet);
		}
		
		public function testPreconditionsMetAfterSingleAdd() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
			
			var eventSource:FictiveTask = new FictiveTask();
			var precondition:EventDescriptor = new EventDescriptor(
					eventSource, 
					"start");
			
			preconditionsManager.add(precondition);
			assertFalse(
					"aPreconditionsManager.mPreconditions checklist should not be met after adding a new precondition",
					preconditionsManager.PreconditionsMet);
			
			// meet precondition and assert that preconditions checklist is met:
			eventSource.start();
			assertTrue(
					"aPreconditionsManager.PreconditionsMet should be true",
					preconditionsManager.PreconditionsMet);
		}
		
		public function testPreconditionsMetAfterMultipleAdd() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
				
			var eventSource1:FictiveTask = new FictiveTask();
			var precondition1:EventDescriptor = new EventDescriptor(
					eventSource1, 
					"start");
			preconditionsManager.add(precondition1);
			
			var eventSource2:FictiveTask = new FictiveTask();
			var precondition2:EventDescriptor = new EventDescriptor(
					eventSource2, 
					"start");
			preconditionsManager.add(precondition2);
			
			assertFalse(
					"aPreconditionsManager.mPreconditions checklist should not be met after adding two new preconditions",
					preconditionsManager.PreconditionsMet);
			
			// meet precondition1 and assert that preconditions checklist is still 
			// not met(precondition2 is not met yet):
			eventSource1.start();
			assertFalse(
					"aPreconditionsManager.PreconditionsMet should be false (there is still precondition that is not met)",
					preconditionsManager.PreconditionsMet);
			
			// meet precondition2 and assert that all preconditions in the 
			// checklist are met:
			eventSource2.start();
			assertTrue(
					"aPreconditionsManager.PreconditionsMet should be true - all preconditions are met",
					preconditionsManager.PreconditionsMet);
		}
		
		public function testReset() : void
		{
			var initialIsAccepting:Boolean = true;
			var preconditionsManager:PreconditionsManager 
				= new PreconditionsManager(initialIsAccepting);
			
			var eventSource1:FictiveTask = new FictiveTask();
			var precondition1:EventDescriptor = new EventDescriptor(
					eventSource1, 
					"start");
			preconditionsManager.add(precondition1);
			
			var eventSource2:FictiveTask = new FictiveTask();
			var precondition2:EventDescriptor = new EventDescriptor(
					eventSource2, 
					"start");
			preconditionsManager.add(precondition2);
			
			eventSource1.start();
			eventSource2.start();
			assertTrue(
					"preconditionsManager.PreconditionsMet should be true - all preconditions are met",
					preconditionsManager.PreconditionsMet);
			
			preconditionsManager.reset();
			
			assertTrue(
					"preconditionsManager should still have precondition1 after reset", 
					preconditionsManager.contains(precondition1));
					
			assertTrue(
					"preconditionsManager should still have precondition2 after reset", 
					preconditionsManager.contains(precondition2));
			
			assertFalse(
					"preconditionsManager.PreconditionsMet should be not true - all preconditions are reset to listen again",
					preconditionsManager.PreconditionsMet);
			
			eventSource1.start();
			eventSource2.start();
			assertTrue(
					"preconditionsManager.PreconditionsMet should be true - all preconditions are met after reset",
					preconditionsManager.PreconditionsMet);
		}
	
		private function fictiveEventHandler(aEvent : Event) : void
		{
			mIsEventDispatched = true;
		} 
	
		private function onPreconditionsMet() : void
		{
			this.preconditionsMet = true;
		}
		
		private function reset() : void
		{
			this.preconditionsMet = false;
		}
	
			
	}
}